package trade

import (
	"github.com/gin-gonic/gin"
	uuid "github.com/satori/go.uuid"
	"go.mongodb.org/mongo-driver/bson"
	"higame/modules/log"
	"higame/modules/store"
	"higame/modules/utils"
	_log "higame/routes/log"
	"higame/routes/order"
	"higame/routes/user"
	"net/http"
)

func create(ctx *gin.Context) {
	v, err := validatorTrade(ctx)
	if err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"code": http.StatusBadRequest,
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}

	err = AddOne(&Schema{
		UUID:        uuid.NewV1().String(),
		AddTime:     utils.Timestamp(),
		EndTime:     v.EndTime,
		Title:       v.Title,
		Subtitle:    v.Subtitle,
		Price:       v.Price,
		Quantity:    v.Quantity,
		GoodsType:   v.GoodsType,
		Belongs:     v.Belongs,
		Seller:      v.Seller,
		MainImage:   v.MainImage,
		DetailImage: v.DetailImage,
		SafeType:    v.SafeType,
	})
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"code": http.StatusInternalServerError,
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"code": http.StatusOK,
		"msg":  "添加成功！",
		"data": nil,
	})
}

func delete(ctx *gin.Context) {
	uuid := ctx.PostForm("uuid")
	err := DeleteOneByUUID(uuid)

	if err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"code": http.StatusBadRequest,
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}
	ctx.JSON(http.StatusOK, gin.H{
		"code": http.StatusOK,
		"msg":  "删除成功",
		"data": nil,
	})
}

func update(ctx *gin.Context) {
	v, err := validatorTrade(ctx)
	if err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"code": http.StatusBadRequest,
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}
	if err = UpdateOneByUUID(v.UUID, bson.M{
		"title":        v.Title,
		"seller":       v.Seller,
		"subtitle":     v.Subtitle,
		"price":        v.Price,
		"quantity":     v.Quantity,
		"end_time":     v.EndTime,
		"belongs":      v.Belongs,
		"goods_type":   v.GoodsType,
		"safe_type":    v.SafeType,
		"main_image":   v.MainImage,
		"detail_image": v.DetailImage,
	}); err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"code": http.StatusInternalServerError,
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"code": http.StatusOK,
		"msg":  "修改成功！",
		"data": nil,
	})
}

func list(ctx *gin.Context) {
	v, err := validatorForList(ctx)
	if err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"code": http.StatusBadRequest,
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}
	filter := bson.M{
		"title": bson.M{
			"$regex":   v.Keyword,
			"$options": "$i",
		},
		"seller": bson.M{
			"$regex":   v.Seller,
			"$options": "$i",
		},
	}

	if v.Belongs != "-1" {
		filter["belongs"] = v.Belongs
	}

	if v.GoodsType != "-1" {
		filter["goods_type"] = v.GoodsType
	}

	priceFilter := bson.M{
		"$gte": v.StartPrice,
	}
	if v.EndPrice > 0 {
		priceFilter["$lte"] = v.EndPrice
	}
	filter["price"] = priceFilter

	list, _ := FindMany(v.PageNum, filter)
	count, _ := Count(filter)

	var str string = ""
	if count == 0 {
		str = "没有查询到数据！"
	} else {
		str = utils.JoinString("共%v页%v行 当前在第%v页", count/20+1, count, v.PageNum+1)
	}
	ctx.JSON(http.StatusOK, gin.H{
		"code": http.StatusOK,
		"msg":  str,
		"data": gin.H{
			"list":  list,
			"total": count,
		},
	})
}

func allList(ctx *gin.Context) {
	v, err := validatorForList(ctx)
	if err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"code": http.StatusBadRequest,
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}

	// 标题与卖家
	// 下架与库存为0不返回
	filter := bson.M{
		"title": bson.M{
			"$regex":   v.Keyword,
			"$options": "$i",
		},
		"seller": bson.M{
			"$regex":   v.Seller,
			"$options": "$i",
		},
		"end_time": bson.M{
			"$gt": 0,
		},
		"quantity": bson.M{
			"$gt": 0,
		},
	}

	// 游戏区服
	if v.Belongs != "-1" {
		filter["belongs"] = v.Belongs
	}

	// 物品类型
	if v.GoodsType != "-1" {
		filter["goods_type"] = v.GoodsType
	}

	// 价格
	priceFilter := bson.M{
		"$gte": v.StartPrice,
	}
	if v.EndPrice > 0 {
		priceFilter["$lte"] = v.EndPrice
	}
	filter["price"] = priceFilter

	list, _ := FindMany(v.PageNum, filter)
	count, _ := Count(filter)

	var str string = ""
	if count == 0 {
		str = "没有查询到数据！"
	} else {
		str = utils.JoinString("共%v页%v行 当前在第%v页", count/20+1, count, v.PageNum+1)
	}
	ctx.JSON(http.StatusOK, gin.H{
		"code": http.StatusOK,
		"msg":  str,
		"data": gin.H{
			"list":  list,
			"total": count,
		},
	})
}

func myCreate(ctx *gin.Context) {
	t, err := validatorTradeForMe(ctx)
	if err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"code": http.StatusBadRequest,
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}

	if err = AddOne(&Schema{
		UUID:        uuid.NewV1().String(),
		AddTime:     utils.Timestamp(),
		EndTime:     t.EndTime,
		Title:       t.Title,
		Subtitle:    t.Subtitle,
		Price:       t.Price,
		Quantity:    t.Quantity,
		GoodsType:   t.GoodsType,
		Belongs:     t.Belongs,
		Seller:      t.Seller,
		MainImage:   t.MainImage,
		DetailImage: t.DetailImage,
		SafeType:    t.SafeType,
	}); err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"code": http.StatusInternalServerError,
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"code": http.StatusOK,
		"msg":  "添加成功！",
		"data": nil,
	})
}

func myDelete(ctx *gin.Context) {
	claims, err := store.GetClaims(ctx)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"code": http.StatusInternalServerError,
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}
	uuid := ctx.PostForm("uuid")
	if v, err := FindOneByUUID(uuid); err != nil {
		// 没有这个交易
		ctx.JSON(http.StatusBadRequest, gin.H{
			"code": http.StatusBadRequest,
			"msg":  "uuid参数出错",
			"data": nil,
		})
		return
	} else if v.Seller != claims.Audience {
		// 当前登录的用户没有这个交易
		ctx.JSON(http.StatusBadRequest, gin.H{
			"code": http.StatusBadRequest,
			"msg":  "uuid参数出错",
			"data": nil,
		})
		return
	}

	if err := DeleteOneByUUID(uuid); err != nil {
		// 删除失败
		ctx.JSON(http.StatusBadRequest, gin.H{
			"code": http.StatusBadRequest,
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}
	ctx.JSON(http.StatusOK, gin.H{
		"code": http.StatusOK,
		"msg":  "删除成功",
		"data": nil,
	})
}

func myUpdate(ctx *gin.Context) {
	claims, err := store.GetClaims(ctx)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"code": http.StatusInternalServerError,
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}

	v, err := validatorTradeForMe(ctx)
	if err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"code": http.StatusBadRequest,
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}

	if v, err := FindOneByUUID(v.UUID); err != nil {
		// 没有这个交易
		ctx.JSON(http.StatusBadRequest, gin.H{
			"code": http.StatusBadRequest,
			"msg":  "uuid参数出错",
			"data": nil,
		})
		return
	} else if v.Seller != claims.Audience {
		// 当前登录的用户没有这个交易
		ctx.JSON(http.StatusBadRequest, gin.H{
			"code": http.StatusBadRequest,
			"msg":  "uuid参数出错",
			"data": nil,
		})
		return
	}

	if err = UpdateOneByUUID(v.UUID, bson.M{
		"title":        v.Title,
		"subtitle":     v.Subtitle,
		"price":        v.Price,
		"quantity":     v.Quantity,
		"end_time":     v.EndTime,
		"belongs":      v.Belongs,
		"goods_type":   v.GoodsType,
		"safe_type":    v.SafeType,
		"main_image":   v.MainImage,
		"detail_image": v.DetailImage,
	}); err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"code": http.StatusInternalServerError,
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"code": http.StatusOK,
		"msg":  "修改成功！",
		"data": nil,
	})
}

func myList(ctx *gin.Context) {
	claims, err := store.GetClaims(ctx)
	if err != nil {
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"code": http.StatusInternalServerError,
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}

	v, err := validatorForList(ctx)

	// 数据验证失败
	if err != nil {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"code": http.StatusBadRequest,
			"msg":  err.Error(),
			"data": nil,
		})
		return
	}

	// 初始化查询过滤器
	filter := bson.M{
		"title": bson.M{
			"$regex":   v.Keyword,
			"$options": "$i",
		},
		"seller": bson.M{
			"$regex":   claims.Audience,
			"$options": "$i",
		},
	}

	if v.Belongs != "-1" {
		filter["belongs"] = v.Belongs
	}

	if v.GoodsType != "-1" {
		filter["goods_type"] = v.GoodsType
	}

	priceFilter := bson.M{
		"$gte": v.StartPrice,
	}
	if v.EndPrice > 0 {
		priceFilter["$lte"] = v.EndPrice
	}
	filter["price"] = priceFilter

	list, _ := FindMany(v.PageNum, filter)
	count, _ := Count(filter)

	var str string = ""
	if count == 0 {
		str = "没有查询到数据！"
	} else {
		str = utils.JoinString("共%v页%v行 当前在第%v页", count/20+1, count, v.PageNum+1)
	}
	ctx.JSON(http.StatusOK, gin.H{
		"code": http.StatusOK,
		"msg":  str,
		"data": gin.H{
			"list":  list,
			"total": count,
		},
	})
}

func goodsType(ctx *gin.Context) {
	ctx.JSON(http.StatusOK, gin.H{
		"code": http.StatusOK,
		"msg":  "获取成功！",
		"data": []gin.H{
			gin.H{
				"key":   "游戏账号",
				"value": Account,
			},
			gin.H{
				"key":   "游戏装备",
				"value": Gun,
			},
			gin.H{
				"key":   "游戏金币",
				"value": Gold,
			},
		},
	})
}

func buy(ctx *gin.Context) {
	goodsId := ctx.PostForm("goods_id")
	quantity := utils.StringToInt64(ctx.PostForm("quantity"), 0)
	if goodsId == "" || quantity <= 0 {
		ctx.JSON(400, gin.H{
			"code": 400,
			"msg":  "参数出错",
			"data": nil,
		})
		return
	}

	//获取当前登录的用户资料
	userItem := user.New()
	if u, err := store.GetClaims(ctx); err != nil {
		log.Error.Println(err)
		ctx.JSON(500, gin.H{
			"code": 500,
			"msg":  "服务器内部出错",
			"data": nil,
		})
		return
	} else if userItem, err = user.FindOneByName(u.Audience); err != nil {
		ctx.JSON(400, gin.H{
			"code": 400,
			"msg":  "当前你要购买的商品不存在",
			"data": nil,
		})
		return
	}

	// 获取商品资料
	goodsItem, err := FindOneByUUID(goodsId)
	if err != nil {
		ctx.JSON(400, gin.H{
			"code": 400,
			"msg":  "当前你要购买的商品不存在",
			"data": nil,
		})
		return
	}
	// 卖家不能与自己交易
	if goodsItem.Seller == userItem.Username {
		ctx.JSON(400, gin.H{
			"code": 400,
			"msg":  "你不能购买自己发布的商品",
			"data": nil,
		})
		return
	}
	// 检测余额
	if float64(userItem.Integral) < goodsItem.Price*float64(quantity) {
		ctx.JSON(400, gin.H{
			"code": 400,
			"msg":  "您没有足够的积分来购买此商品",
			"data": nil,
		})
		return
	}

	// 检测库存
	if goodsItem.Quantity < quantity {
		ctx.JSON(400, gin.H{
			"code": 400,
			"msg":  "库存不足",
			"data": nil,
		})
		return
	}
	// 创建订单
	if err := order.AddOne(&order.Schema{
		Seller:      goodsItem.Seller,
		Buyer:       userItem.Username,
		Quantity:    quantity,
		OrderID:     uuid.NewV1().String(),
		AddTime:     utils.Timestamp(),
		FHTime:      0,
		SHTime:      0,
		QXTime:      0,
		GoodsID:     goodsItem.UUID,
		Title:       goodsItem.Title,
		MainImage:   goodsItem.MainImage,
		Price:       goodsItem.Price,
		Remark:      utils.JoinString("%v - %v", goodsItem.Belongs, goodsItem.GoodsType),
		OrderStatus: order.FK,
		PayType:     order.IntegralPay,
		OrderType:   order.Game,
	}); err != nil {
		log.Error.Println(err)
		ctx.JSON(500, gin.H{
			"code": 500,
			"msg":  "服务器内部出错",
			"data": nil,
		})
		return
	}

	// 修改用户积分
	if err := user.UpdateOne(bson.M{
		"username": userItem.Username,
	}, bson.M{
		"$inc": bson.M{
			"integral": 0 - int64(goodsItem.Price)*quantity,
		},
	}); err != nil {
		log.Error.Println(err)
		ctx.JSON(500, gin.H{
			"code": 500,
			"msg":  "服务器内部出错",
			"data": nil,
		})
		return
	}

	// 添加积分日志
	if err := _log.AddOneIntegralLog(&_log.IntegralLogSchema{
		UUID:     uuid.NewV1().String(),
		AddTime:  utils.Timestamp(),
		Username: userItem.Username,
		Integral: 0 - int64(goodsItem.Price)*quantity,
		Text:     "游戏装备交易",
		Other:    utils.JoinString("%v x %v", goodsItem.Title, quantity),
	}); err != nil {
		log.Error.Println(err)
		ctx.JSON(500, gin.H{
			"code": 500,
			"msg":  "服务器内部出错",
			"data": nil,
		})
		return
	}

	// 库存操作，这边有一个问题就是并发购买是否会同时操作库存
	// 我这里暂时不做相应的处理
	if err := UpdateOne(bson.M{"uuid": goodsId}, bson.M{
		"$inc": bson.M{
			"quantity": 0 - quantity,
		},
	}); err != nil {
		ctx.JSON(400, gin.H{
			"code": 400,
			"msg":  "修改库存失败",
			"data": nil,
		})
		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"code": http.StatusOK,
		"msg":  "支付成功，等待发货！",
		"data": nil,
	})
}
